package com.example.billin.opengltest.shader.render

import android.content.Context
import android.graphics.Color
import android.opengl.Matrix
import android.util.Log
import com.example.billin.opengltest.BuildConfig
import com.example.billin.opengltest.shader.program.CloseLineProgram
import com.example.billin.opengltest.shader.program.RoundCapLineProgram
import com.example.billin.opengltest.shader.program.apply
import com.example.billin.opengltest.shader.program.draw
import com.example.billin.opengltest.visualizer.PiecewiseFormula
import com.example.billin.opengltest.visualizer.VisualizerCalculateUtil
import com.example.billin.opengltest.visualizer.VisualizerRender

/**
 * Created by xfengimacgomo
 * data 2019/4/18 10:13
 * email xfengv@yeah.net
 */
class GriddingLineRender(val context: Context) : VisualizerRender() {
    private val CYLINDER_WIDTH = 100

    /**
     * 需要的数据大小
     */
    private val DATA_LENGTH = 80

    private val projectMatrix: FloatArray = FloatArray(16)
    private val viewMatrix: FloatArray = FloatArray(16)
    private val viewProjectMatrix: FloatArray = FloatArray(16)


    //圆柱
    private val cylinderData: FloatArray = FloatArray(DATA_LENGTH * 4)

    //todo 等下确认一下这个长度到底对不对
    private val closelinderData: FloatArray = FloatArray(DATA_LENGTH * 4 )

    private var lastDrawTime: Long = 0

    private var centerX = 0f

    private var centerY = 0f

    private var innerWidth = 0f

    private var size = 0f


    //绘制线
    private lateinit var roundLineProgram: RoundCapLineProgram

    private lateinit var closeLineProgram: CloseLineProgram


    override fun processData(rawData: FloatArray?, length: Int): Int {
        val cropLength = (length - DATA_LENGTH * 2) / 2
        VisualizerCalculateUtil.cropOriginFftData(
            rawData,
            cropLength,
            cropLength,
            length
        )
        VisualizerCalculateUtil.processFftMagnitudeData(
            rawData,
            DATA_LENGTH * 2
        )
        VisualizerCalculateUtil.flatData(rawData,
            PiecewiseFormula(Math.hypot(128.0, 128.0).toFloat(), CYLINDER_WIDTH.toFloat(), 5f, 5f),
            DATA_LENGTH
        )

        return DATA_LENGTH
    }

    private companion object {
        private const val TAG = "GriddingLineRender"
    }

    private val timeArray = LongArray(60)
    private var timeIndex = 0

    override fun draw(processedData: FloatArray?) {
        processedData ?: return
        //radius=屏幕宽度的2/3
        val radius = innerWidth / 2

        //绘制当前帧的时间
        val currentDrawTime = System.currentTimeMillis()
        //间隔时间
        val intervalTime = currentDrawTime - lastDrawTime

        if (BuildConfig.DEBUG) {
            timeArray[timeIndex] = intervalTime
            timeIndex = (timeIndex + 1) % timeArray.size
            if (timeIndex == 0) Log.d(TAG, "draw: ${1000.0 / timeArray.average()}")
        }

        lastDrawTime = currentDrawTime

        for (i in 0 until DATA_LENGTH) {
            val degree = i.toDouble() / DATA_LENGTH * 2.0 * Math.PI
            val cosDegree = Math.cos(degree)
            var sinDegree = Math.sin(degree)

            val ci = i * 4
            //processedData是音频数据的一个值
            val endRadius = radius + processedData[i]
            //这里是前后两个点:inner(x,y)   out(x,y)
            cylinderData[ci] = (sinDegree * radius).toFloat()
            cylinderData[ci + 1] = (cosDegree * radius).toFloat()
            cylinderData[ci + 2] = (sinDegree * endRadius).toFloat()
            cylinderData[ci + 3] = (cosDegree * endRadius).toFloat()

            //val ci2 = i * 2
            closelinderData[ci] =(sinDegree * endRadius).toFloat()
            closelinderData[ci+1] =(cosDegree * endRadius).toFloat()
            closelinderData[ci+2] =(sinDegree * (endRadius+5)).toFloat()
            closelinderData[ci+3] =(cosDegree * (endRadius+5)).toFloat()
        }


        roundLineProgram.draw {
            bindLines(cylinderData, cylinderData.size)
        }
        closeLineProgram.draw {
            bindLines(closelinderData, closelinderData.size)
        }
    }

    override fun onResize(width: Float, height: Float) {
        centerX = width / 2
        centerY = height / 2

        this.size = Math.min(width, height)
        this.innerWidth = width * 2 / 3

        Matrix.orthoM(
            projectMatrix, 0, 0f, width,
            height, 0f, -1f, 1f
        )
        Matrix.setIdentityM(viewMatrix, 0)
        Matrix.translateM(viewMatrix, 0, centerX, centerY, 0f)
        Matrix.multiplyMM(viewProjectMatrix, 0, projectMatrix, 0, viewMatrix, 0)

        roundLineProgram.apply {
            setMatrix(viewProjectMatrix)
            setSize(5)
            setAntialias(1f)
            setColor(Color.parseColor("#AB82FF"))
        }

        closeLineProgram.apply {
            setMatrix(viewProjectMatrix)
            setSize(5)
            setAntialias(1f)
            setColor(Color.parseColor("#AB82FF"))
        }
    }

    override fun surfaceCreated() {
        roundLineProgram = RoundCapLineProgram(context)
        closeLineProgram = CloseLineProgram(context)
    }
}